define(
[
    "factory/POIFactory",
    "factory/GroundsFactory",
    "render/poi/POIRendererMgr"
],
function(
    POIFactory,
    GroundsFactory,
    POIRendererMgr
    ){
    return {
        create: function() {

            var _self = {
                init: function(systemMgr, url, doneCallback) {
                    //Destroy if already instantiated
                    if(_hasInit)
                        _self.destroy();

                    //Assign vars
                    _hasInit        = true;
                    _systemMgr      = systemMgr;
                    _POIs           = [];
                    _grounds        = [];
                    _POIRendererMgr = POIRendererMgr.create();
                    _doneCallback   = doneCallback;

                    //Load the osm XML
                    $.get(url, null, _onOSMLoaded, "xml");

                    return this;
                },

                getCenterPos: function() {
                    return _centerPos;
                },

                getBounds: function() {
                    return _bounds;
                },

                destroy: function() {
                    throw "not implemented!";

                    //Destroy all entities
                    for(var idx in _POIs)
                        _POIs[idx].destroy();
                    for(var idx in _grounds)
                        _grounds[idx].destroy();

                    //Destroy the batch
                    _POIRendererMgr.destroy();

                    //Declare as not init
                    _hasInit = false;
                }
            };


            var _hasInit = false;
            var _POIRendererMgr;
            var _systemMgr;
            var _POIs;
            var _grounds;
            var _centerPos;
            var _bounds;
            var _doneCallback;

            function _onPOIsCreated(POIs) {
                _POIs = _POIs.concat(POIs);
                _POIRendererMgr.finalize();
            }

            function _createLatLonToMeterConverter(xml) {
                var bounds = $(xml).find("bounds")[0];
                var minLat = +$(bounds).attr("minlat");
                var minLon = +$(bounds).attr("minlon");
                return Math.createLatLonToMeterConverter(minLon, minLat);
            }

            function _calculateCenterPos(xml, converter) {
                var bounds = $(xml).find("bounds")[0];
                var minLat = +$(bounds).attr("minlat");
                var minLon = +$(bounds).attr("minlon");
                var maxLat = +$(bounds).attr("maxlat");
                var maxLon = +$(bounds).attr("maxlon");

                _centerPos = [(maxLat+minLat)/2, 0, (maxLon+minLon)/2];
                _centerPos[0] = converter.latToMeter(_centerPos[0]);
                _centerPos[2] = converter.lonToMeter(_centerPos[2]);
                _bounds = [
                    converter.latToMeter(minLat),
                    converter.lonToMeter(minLon),
                    converter.latToMeter(maxLat),
                    converter.lonToMeter(maxLon),
                ];
            }

            function _onOSMLoaded(xml) {
                //Create converter
                var converter = _createLatLonToMeterConverter(xml);

                //Calc center pos
                _calculateCenterPos(xml, converter);

                //Create entities
                _POIRendererMgr.init(_systemMgr);
                POIFactory.createPOIs(
                    xml, _POIRendererMgr, _systemMgr, 
                    converter, _onPOIsCreated
                );

                //Create grounds
                GroundsFactory.createGrounds(_systemMgr, xml, converter, _grounds);

                //Done
                _doneCallback(_self);
            }

            return _self;
        }
    };
});